package com.run_java_test.jar_upload_run.services.v1;

import com.alibaba.fastjson2.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class JarClassRegisterService {

    // spring 上下文
    private final ApplicationContext applicationContext;
    // 请求地址和方法映射处理类
    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Autowired
    public JarClassRegisterService(
            ApplicationContext applicationContext,
            RequestMappingHandlerMapping requestMappingHandlerMapping
    ) {
        this.applicationContext = applicationContext;
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    // 用于存储 controller 的映射信息
    private final Map<RequestMappingInfo, Object> registeredControllers = new ConcurrentHashMap<>();

    // 合并路径方法
    private String[] combinePaths(String[] classLevelPaths, String[] methodLevelPaths) {
        if (classLevelPaths.length == 0) {
            return methodLevelPaths; // 没有类级别路径，直接返回方法级别路径
        }
        List<String> combinedPaths = new ArrayList<>();
        for (String classPath : classLevelPaths) {
            for (String methodPath : methodLevelPaths) {
                String combinedPath = classPath + "/" + methodPath;
                combinedPaths.add(combinedPath.replaceAll("//+", "/")); // 确保路径中不会出现多个连续的斜杠
            }
        }
        return combinedPaths.toArray(new String[0]);
    }

    // 注册jar中的controller
    public void registerController(Class<?> controllerClass) throws Exception {
        Annotation[] annotations = controllerClass.getAnnotations();
        System.out.println(JSON.toJSONString(annotations));

        // 如果类上面有controller相关注解
        if (controllerClass.isAnnotationPresent(RestController.class)) {

            // 检查类级别路径
            String[] classLevelPaths = {};
            if (controllerClass.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping classRequestMapping = controllerClass.getAnnotation(RequestMapping.class);
                classLevelPaths = classRequestMapping.value();
            }

            try {
                // 获取类名并将首字母小写
                String beanName = controllerClass.getSimpleName();
                beanName = Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1);
                Object controllerInstance = applicationContext.getBean(beanName);
//                // 创建控制器实例
//                Object controllerInstance = applicationContext.getAutowireCapableBeanFactory().createBean(controllerClass);
//                // 手动注入依赖（如果有未注入的依赖）
//                applicationContext.getAutowireCapableBeanFactory().autowireBean(controllerInstance);

                // 获取方法的所有方法
                for (Method method : controllerClass.getDeclaredMethods()) {
                    // 获取被 GetMapping 注解标识的方法
                    if (method.isAnnotationPresent(RequestMapping.class)) {
                        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);

                        System.out.println("查看 RequestMapping requestMapping.value() : " + JSON.toJSONString(requestMapping.value()));

                        // 合并类级别路径和方法级别路径
                        String[] fullPaths = combinePaths(classLevelPaths, requestMapping.value());

                        // 创建 RequestMappingInfo
                        RequestMappingInfo mappingInfo = RequestMappingInfo
                                .paths(fullPaths)
                                .methods(requestMapping.method())
                                .produces(requestMapping.produces())
                                .consumes(requestMapping.consumes())
                                .build();

                        // 注册 HandlerMethod
                        requestMappingHandlerMapping.registerMapping(mappingInfo, controllerInstance, method);

                        // 保存注册的信息
                        registeredControllers.put(mappingInfo, controllerInstance);

                        System.out.println("注册 RequestMapping 类型的方法成功");
                    }

                    // 获取被 GetMapping 注解标识的方法
                    if (method.isAnnotationPresent(GetMapping.class)) {
                        GetMapping requestMapping = method.getAnnotation(GetMapping.class);

                        // 合并类级别路径和方法级别路径
                        String[] fullPaths = combinePaths(classLevelPaths, requestMapping.value());

                        System.out.println("查看 GetMapping requestMapping.value() : " + JSON.toJSONString(requestMapping.value()));

                        // 构造 RequestMappingInfo
                        RequestMappingInfo mappingInfo = RequestMappingInfo
                                .paths(fullPaths)            // 路径
                                .methods(RequestMethod.GET)           // 强制指定为 GET 方法
                                .produces(requestMapping.produces())      // 返回类型
                                .consumes(requestMapping.consumes())      // 消费类型
                                .build();

                        // 注册 HandlerMethod
                        requestMappingHandlerMapping.registerMapping(mappingInfo, controllerInstance, method);

                        // 保存注册的信息
                        registeredControllers.put(mappingInfo, controllerInstance);

                        System.out.println("注册 GetMapping 类型的方法成功");
                    }
                }
            } catch (Exception e) {
                System.out.println("注册bean出现异常 : " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    // 注销jar中的controller
    public void unregisterController(Class<?> controllerClass) {
        if (controllerClass.isAnnotationPresent(RestController.class)) {

            // 检查类级别路径
            String[] classLevelPaths = {};
            if (controllerClass.isAnnotationPresent(RequestMapping.class)) {
                RequestMapping classRequestMapping = controllerClass.getAnnotation(RequestMapping.class);
                classLevelPaths = classRequestMapping.value();
            }

            for (Method method : controllerClass.getDeclaredMethods()) {
                // 如果方法是 RequestMapping 类型 的请求
                if (method.isAnnotationPresent(RequestMapping.class)) {

                    RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);

                    // 合并类级别路径和方法级别路径
                    String[] fullPaths = combinePaths(classLevelPaths, requestMapping.value());

                    RequestMappingInfo mappingInfo = RequestMappingInfo
                            .paths(fullPaths)
                            .methods(requestMapping.method())
                            .produces(requestMapping.produces())
                            .consumes(requestMapping.consumes())
                            .build();

                    // 从注册的信息中移除映射
                    Object controllerInstance = registeredControllers.remove(mappingInfo);

                    // 如果当前springmvc容器中有内容
                    if (controllerInstance != null) {
                        // 注销映射
                        requestMappingHandlerMapping.unregisterMapping(mappingInfo);
                    }
                }

                // 如果是 get 类型的请求
                if (method.isAnnotationPresent(GetMapping.class)) {

                    GetMapping requestMapping = method.getAnnotation(GetMapping.class);

                    // 合并类级别路径和方法级别路径
                    String[] fullPaths = combinePaths(classLevelPaths, requestMapping.value());

                    RequestMappingInfo mappingInfo = RequestMappingInfo
                            .paths(fullPaths)
                            .methods(RequestMethod.GET)
                            .produces(requestMapping.produces())
                            .consumes(requestMapping.consumes())
                            .build();

                    // 从注册的信息中移除映射
                    Object controllerInstance = registeredControllers.remove(mappingInfo);

                    // 如果当前springmvc容器中有内容
                    if (controllerInstance != null) {
                        // 注销映射
                        requestMappingHandlerMapping.unregisterMapping(mappingInfo);
                    }
                }
            }
        }

//        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
//
//        // 获取类名并将首字母小写
//        String beanName = controllerClass.getSimpleName();
//        beanName = Character.toLowerCase(beanName.charAt(0)) + beanName.substring(1);
//        // 检查是否存在同名 Bean
//        if (beanFactory.containsBeanDefinition(beanName)) {
//            // 移除旧的 Bean 定义
//            beanFactory.removeBeanDefinition(beanName);
//            System.out.println("根据 beanName 卸载 bean , beanName = " + beanName);
//        }

    }
}
